package co.yixiang.yshop.module.distributor.service.distributor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.framework.common.util.collection.CollectionUtils;
import co.yixiang.yshop.framework.dict.core.util.DictFrameworkUtils;
import co.yixiang.yshop.module.distributor.controller.admin.distributor.vo.*;
import co.yixiang.yshop.module.distributor.controller.admin.distributorlevel.vo.DistributorLevelExportReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributororder.vo.DistributorOrderExportReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributoruser.vo.DistributorUserCreateReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributoruser.vo.DistributorUserExportReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributoruser.vo.DistributorUserUpdateReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwages.vo.DistributorWagesCreateReqVO;
import co.yixiang.yshop.module.distributor.controller.admin.distributorwithdrawalmethod.vo.DistributorWithdrawalMethodCreateReqVO;
import co.yixiang.yshop.module.distributor.controller.app.distributor.vo.AppDistributorApplyReqVO;
import co.yixiang.yshop.module.distributor.controller.app.distributor.vo.AppDistributorDetailsRespVO;
import co.yixiang.yshop.module.distributor.controller.app.distributor.vo.AppDistributorUpdateReqVO;
import co.yixiang.yshop.module.distributor.controller.app.distributorproduct.vo.AppDistributorProductRespVO;
import co.yixiang.yshop.module.distributor.convert.distributor.DistributorConvert;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributor.DistributorDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributorlevel.DistributorLevelDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributororder.DistributorOrderDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributoruser.DistributorUserDO;
import co.yixiang.yshop.module.distributor.dal.dataobject.distributorwages.DistributorWagesDO;
import co.yixiang.yshop.module.distributor.enums.*;
import co.yixiang.yshop.module.distributor.service.distributorlevel.DistributorLevelFacade;
import co.yixiang.yshop.module.distributor.service.distributorlevel.DistributorLevelService;
import co.yixiang.yshop.module.distributor.service.distributororder.DistributorOrderService;
import co.yixiang.yshop.module.distributor.service.distributoruser.DistributorUserService;
import co.yixiang.yshop.module.distributor.service.distributorwages.DistributorWagesService;
import co.yixiang.yshop.module.distributor.service.distributorwithdrawalmethod.DistributorWithdrawalMethodService;
import co.yixiang.yshop.module.member.api.user.MemberUserApi;
import co.yixiang.yshop.module.member.api.user.dto.MemberUserRespDTO;
import co.yixiang.yshop.module.product.api.product.ProductApi;
import co.yixiang.yshop.module.product.api.product.dto.ProductDTO;
import co.yixiang.yshop.module.product.api.product.dto.ProductPageReqVO;
import co.yixiang.yshop.module.system.enums.DistributorDictEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

@Slf4j
@Service
@Validated
public class DistributorFacadeImpl implements DistributorFacade {

    @Resource
    private DistributorService distributorService;

    @Resource
    private DistributorLevelService distributorLevelService;

    @Resource
    private DistributorUserService distributorUserService;

    @Resource
    private DistributorWagesService distributorWagesService;

    @Resource
    private DistributorWithdrawalMethodService distributorWithdrawalMethodService;

    @Resource
    private MemberUserApi memberUserApi;

    @Resource
    private DistributorOrderService distributorOrderService;

    @Resource
    private ProductApi productApi;

    @Lazy
    @Resource
    private DistributorLevelFacade distributorLevelFacade;

    /**
     * APP获取分销商详情
     * 根据状态判断分销商步骤
     *
     * @return 分销商详情
     */
    @Override
    public AppDistributorDetailsRespVO getAppDetails() {
        AppDistributorDetailsRespVO respVO = new AppDistributorDetailsRespVO();
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        if (distributorDO != null) {
            // 获取等级
            DistributorLevelDO level = distributorLevelService.getLevel(distributorDO.getLevelId());
            BeanUtil.copyProperties(distributorDO, respVO);
            respVO.setLevelName(level.getName());
            if (distributorDO.getSuperiorIdP1() != null) {
                // 所属一级分销商
                DistributorDO superiorDistributorDO = distributorService.get(distributorDO.getSuperiorIdP1());
                respVO.setSuperiorName(superiorDistributorDO.getRealName());
            }
            // 佣金
            respVO.setAddUpWages(distributorDO.getAddUpWages());
            DistributorWagesDO distributorWagesDO = distributorWagesService.getWagesByDistributorId(distributorDO.getId());
            if (distributorWagesDO != null) {
                respVO.setAmount(distributorWagesDO.getAmount());
                respVO.setRefuseAmount(distributorWagesDO.getRefuseAmount());
            }
        }
        return respVO;
    }

    @Override
    public void apply(AppDistributorApplyReqVO reqVO) {
        // 获取分销商
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        if (distributorDO != null) {
            // 不是拒绝
            if (!DistributorStatusEnum.REFUSED.getStatus().equals(distributorDO.getStatus())) {
                throw exception(ErrorCodeConstants.DISTRIBUTOR_USER_EXISTS);
            }

        } else {
            // 未申请过分销商
            distributorDO = new DistributorDO();
        }

        distributorDO.setUserId(userId);
        distributorDO.setRealName(reqVO.getRealName());
        distributorDO.setAddress(reqVO.getAddress());
        distributorDO.setReason(reqVO.getReason());

        // 默认等级
        DistributorLevelDO defaultLevel = distributorLevelService.getDefaultLevel();
        distributorDO.setLevelId(defaultLevel.getId());
        distributorDO.setStatus(DistributorStatusEnum.AUDIT.getStatus());

        // 判断是否别人邀请推荐
        if (reqVO.getSuperiorIdP1() != null) {
            // 绑定一级分销商
            DistributorDO p1 = distributorService.get(reqVO.getSuperiorIdP1());
            distributorDO.setSuperiorIdP1(p1.getId());
            distributorDO.setSuperiorNameP1(p1.getRealName());
            distributorDO.setSuperiorIdP2(p1.getSuperiorIdP1());
            distributorDO.setSuperiorNameP2(p1.getSuperiorNameP1());
            // 绑定用户
            this.bindUser(reqVO.getSuperiorIdP1(), userId, DistributorConstants.TURE_INTEGER);
            // 增加邀请分销商数
            distributorService.addUpDistributor(p1.getId());

        }
        if (distributorDO.getId() == null) {
            // 保存
            Long id = distributorService.save(distributorDO);
            distributorDO.setId(id);
        } else {
            distributorService.update(distributorDO);
        }

        String apply = DictFrameworkUtils.parseDictDataValue(DistributorDictEnum.DISTRIBUTOR_APPLY.getDictType(), DistributorDictEnum.DISTRIBUTOR_APPLY.getLabel());
        if (DistributorConstants.APPLY_TRUE.equals(apply)) {
            // 自动通过
            this.verify(new DistributorApplyReqVO().setId(distributorDO.getId()).setStatus(DistributorStatusEnum.PASSED.getStatus()));
        }
    }

    @Override
    public void appUpdate(AppDistributorUpdateReqVO reqVO) {
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        DistributorUpdateReqVO distributorUpdateReqVO = new DistributorUpdateReqVO();
        distributorUpdateReqVO.setId(distributorDO.getId());
        distributorUpdateReqVO.setRealName(reqVO.getRealName());
        distributorUpdateReqVO.setAddress(reqVO.getAddress());
        distributorUpdateReqVO.setReason(reqVO.getReason());
        distributorService.update(distributorUpdateReqVO);
    }

    @Override
    public DistributorRespVO getDetails(Long id) {
        DistributorDO distributorDO = distributorService.get(id);
        if (distributorDO == null) {
            throw exception(ErrorCodeConstants.DISTRIBUTOR_NOT_EXISTS);
        }
        DistributorRespVO respVO = DistributorConvert.INSTANCE.convert(distributorDO);
        // 获取等级
        DistributorLevelDO level = distributorLevelService.getLevel(respVO.getLevelId());
        // 费率
        respVO.setLevelName(level.getName());
        respVO.setFirstWages(level.getFirstWages());
        respVO.setSecondWages(level.getSecondWages());

        MemberUserRespDTO user = Optional.ofNullable(memberUserApi.getUser(distributorDO.getUserId())).orElseGet(MemberUserRespDTO::new);
        respVO.setMobile(user.getMobile());

        // 获取我的用户
        List<DistributorUserDO> p1UserList = distributorUserService.getUserList(new DistributorUserExportReqVO().setSuperiorIdP1(id));
        List<DistributorUserDO> p2UserList = distributorUserService.getUserList(new DistributorUserExportReqVO().setSuperiorIdP2(id));
        respVO.setP1UserCount(p1UserList.size());
        respVO.setP2UserCount(p2UserList.size());
        respVO.setUserCount(p1UserList.size() + p2UserList.size());

        // 我的分销商
        List<DistributorDO> p1Distributor = distributorService.getList(new DistributorExportReqVO().setSuperiorIdP1(id));
        List<DistributorDO> p2Distributor = distributorService.getList(new DistributorExportReqVO().setSuperiorIdP2(id));
        respVO.setFirstDistributorCount(p1Distributor.size());
        respVO.setSecondDistributorCount(p2Distributor.size());

        // 我的分销订单
        List<DistributorOrderDO> p1OrderList = distributorOrderService.getOrderList(new DistributorOrderExportReqVO().setSuperiorIdP1(id));
        List<DistributorOrderDO> p2OrderList = distributorOrderService.getOrderList(new DistributorOrderExportReqVO().setSuperiorIdP2(id));
        respVO.setOrderCount(p1OrderList.size() + p2OrderList.size());
        respVO.setFirstOrderCount(p1OrderList.size());
        respVO.setSecondOrderCount(p2OrderList.size());

        BigDecimal p1Amount = p1OrderList.stream()
                .map(DistributorOrderDO::getProductPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal p2Amount = p2OrderList.stream()
                .map(DistributorOrderDO::getProductPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        respVO.setFirstAmountCount(p1Amount);
        respVO.setSecondAmountCount(p2Amount);
        respVO.setAmountCount(p1Amount.add(p2Amount));
        return respVO;
    }

    @Override
    public void verify(DistributorApplyReqVO reqVO) {
        DistributorDO distributorDO = distributorService.get(reqVO.getId());
        // 更新状态
        DistributorUpdateReqVO distributorUpdateReqVO = new DistributorUpdateReqVO();
        distributorUpdateReqVO.setId(reqVO.getId());
        distributorUpdateReqVO.setStatus(reqVO.getStatus());
        distributorUpdateReqVO.setRefuse(reqVO.getRefuse());
        distributorService.update(distributorUpdateReqVO);
        // 判断是否通过 保存余额
        if (DistributorStatusEnum.PASSED.getStatus().equals(reqVO.getStatus())) {
            // 保存分销余额
            DistributorWagesCreateReqVO createReqVO = new DistributorWagesCreateReqVO();
            createReqVO.setDistributorId(reqVO.getId());
            createReqVO.setAmount(BigDecimal.ZERO);
            createReqVO.setRefuseAmount(BigDecimal.ZERO);
            createReqVO.setUserId(distributorDO.getUserId());
            distributorWagesService.createWages(createReqVO);
            // 保存提现方式
            DistributorWithdrawalMethodTypeEnum[] distributorWithdrawalMethodTypeEnums = DistributorWithdrawalMethodTypeEnum.values();
            for (DistributorWithdrawalMethodTypeEnum x : distributorWithdrawalMethodTypeEnums) {
                Integer type = x.getType();
                String paymentMethod = x.getPaymentMethod();
                DistributorWithdrawalMethodCreateReqVO distributorWithdrawalMethodCreateReqVO = new DistributorWithdrawalMethodCreateReqVO();
                distributorWithdrawalMethodCreateReqVO.setDistributorId(reqVO.getId());
                distributorWithdrawalMethodCreateReqVO.setType(type);
                distributorWithdrawalMethodCreateReqVO.setPaymentMethod(paymentMethod);
                distributorWithdrawalMethodService.createWithdrawalMethod(distributorWithdrawalMethodCreateReqVO);
            }
        }
    }

    /**
     * 后台清退分销商
     *
     * @param reqVO 传参
     */
    @Override
    public void clearance(DistributorClearanceReqVO reqVO) {
        DistributorDO distributorDO = distributorService.get(reqVO.getId());
        if (distributorDO == null) {
            throw exception(ErrorCodeConstants.DISTRIBUTOR_NOT_EXISTS);
        }
        if (DistributorStatusEnum.NOT_APPLIED.getStatus().equals(distributorDO.getStatus())) {
            // 恢复
            DistributorUpdateReqVO distributorUpdateReqVO = new DistributorUpdateReqVO();
            distributorUpdateReqVO.setId(distributorDO.getId());
            distributorUpdateReqVO.setStatus(DistributorStatusEnum.PASSED.getStatus());
            distributorService.update(distributorUpdateReqVO);
            return;
        }
        DistributorUpdateReqVO distributorUpdateReqVO = new DistributorUpdateReqVO();
        distributorUpdateReqVO.setId(distributorDO.getId());
        distributorUpdateReqVO.setStatus(DistributorStatusEnum.NOT_APPLIED.getStatus());
        distributorUpdateReqVO.setAddUpUser(0);
        distributorUpdateReqVO.setAddUpDistributor(0);
        distributorService.update(distributorUpdateReqVO);
        // 清除所有下级绑定 分销商 用户
        distributorService.clearance(distributorDO.getId());
        distributorUserService.clearance(distributorDO.getId());
    }

    @Override
    public void restore(DistributorClearanceReqVO reqVO) {
        DistributorDO distributorDO = distributorService.get(reqVO.getId());
        if (distributorDO == null) {
            throw exception(ErrorCodeConstants.DISTRIBUTOR_NOT_EXISTS);
        }
        DistributorUpdateReqVO distributorUpdateReqVO = new DistributorUpdateReqVO();
        distributorUpdateReqVO.setId(distributorDO.getId());
        distributorUpdateReqVO.setStatus(DistributorStatusEnum.PASSED.getStatus());
        distributorService.update(distributorUpdateReqVO);
    }

    @Override
    public PageResult<AppDistributorProductRespVO> getProductPage(ProductPageReqVO reqVO) {
        // 获取分销商
        Long userId = getLoginUserId();
        DistributorDO distributorDO = distributorService.getDistributorByUserId(userId);
        if (distributorDO == null) {
            throw exception(ErrorCodeConstants.DISTRIBUTOR_NOT_EXISTS);
        }
        // 获取分销商等级
        DistributorLevelDO level = distributorLevelService.getLevel(distributorDO.getId());

        // 返回值
        PageResult<AppDistributorProductRespVO> result = new PageResult<>();
        List<AppDistributorProductRespVO> list = new ArrayList<>();

        // 获取商品
        reqVO.setIsDistribution(DistributorProductTypeEnum.YES.getType());
        PageResult<ProductDTO> productPage = productApi.getProductPage(reqVO);
        // 获取商品
        List<ProductDTO> productDTOList = productPage.getList();
        // 计算佣金
        for (ProductDTO productDTO : productDTOList) {
            AppDistributorProductRespVO appDistributorProductRespVO = BeanUtil.copyProperties(productDTO, AppDistributorProductRespVO.class);
            appDistributorProductRespVO.setExpectPrice(productDTO.getPrice().multiply(new BigDecimal(100)).divide(new BigDecimal(level.getFirstWages()), 2, RoundingMode.DOWN));
            list.add(appDistributorProductRespVO);
        }
        result.setList(list);
        result.setTotal(productPage.getTotal());
        return result;
    }

    /**
     * 绑定用户
     *
     * @param id            分销商ID
     * @param userId        用户ID
     * @param isDistributor
     * @return
     */
    @Override
    public Long bindUser(Long id, Long userId, Integer isDistributor) {
        // 获取一级分销商
        DistributorDO p1 = distributorService.get(id);

        Date afterSevenDays;
        // 获取客户保护天数
        String day = DictFrameworkUtils.parseDictDataValue(DistributorDictEnum.DISTRIBUTOR_USER_EXPIRE.getDictType(), DistributorDictEnum.DISTRIBUTOR_USER_EXPIRE.getLabel());
        if (day.equals(DistributorConstants.UNLIMITED_USER_EXPIRE)) {
            afterSevenDays = DateUtil.offset(DateUtil.date(), DateField.YEAR, DistributorConstants.UNLIMITED_YEAR);
        } else {
            afterSevenDays = DateUtil.offset(DateUtil.date(), DateField.DAY_OF_MONTH, Integer.parseInt(day));
        }
        // 使用ZoneId系统默认时区将Instant转换为ZonedDateTime
        ZonedDateTime zonedDateTime = afterSevenDays.toInstant().atZone(ZoneId.systemDefault());
        LocalDateTime expireTime = zonedDateTime.toLocalDateTime();


        // 判断用户是否已经绑定
        DistributorUserDO distributorUserDO = distributorUserService.getByUserId(userId);
        if (distributorUserDO == null) {
            // 未绑定
            DistributorUserCreateReqVO createReqVO = new DistributorUserCreateReqVO();
            MemberUserRespDTO user = memberUserApi.getUser(userId);
            createReqVO.setNickname(user.getNickname());
            createReqVO.setAvatar(user.getAvatar());
            createReqVO.setUserId(userId);
            createReqVO.setSuperiorIdP1(p1.getId());
            createReqVO.setSuperiorNameP1(p1.getRealName());
            createReqVO.setSuperiorIdP2(p1.getSuperiorIdP1());
            createReqVO.setSuperiorNameP2(p1.getSuperiorNameP1());
            createReqVO.setExpireTime(expireTime);
            createReqVO.setIsDistributor(isDistributor);
            // 保存绑定关系
            Long user1 = distributorUserService.createUser(createReqVO);
            distributorLevelFacade.levelUp(p1.getId());
            return user1;
        }

        if (distributorUserDO.getExpireTime().isAfter(LocalDateTime.now())) {
            // 已绑定用户 不处理
            return distributorUserDO.getId();
        }

        // 更新绑定关系
        DistributorUserUpdateReqVO updateReqVO = new DistributorUserUpdateReqVO();
        updateReqVO.setId(distributorUserDO.getId());
        updateReqVO.setSuperiorIdP1(p1.getId());
        updateReqVO.setSuperiorNameP1(p1.getRealName());
        updateReqVO.setSuperiorIdP2(p1.getSuperiorIdP1());
        updateReqVO.setSuperiorNameP2(p1.getSuperiorNameP1());
        updateReqVO.setExpireTime(expireTime);
        updateReqVO.setCreateTime(LocalDateTime.now());
        updateReqVO.setIsDistributor(isDistributor);
        distributorUserService.updateUser(updateReqVO);

        distributorLevelFacade.levelUp(p1.getId());
        return distributorUserDO.getId();
    }

    @Override
    public PageResult<DistributorDO> getPage(DistributorPageReqVO pageReqVO) {
        // 获取所有等级
        List<DistributorLevelDO> levelList = distributorLevelService.getLevelList(new DistributorLevelExportReqVO());
        Map<Long, DistributorLevelDO> distributorLevelMap = levelList.stream().collect(Collectors.toMap(DistributorLevelDO::getId, p -> p, (existingValue, newValue) -> existingValue));

        // 查询
        PageResult<DistributorDO> page = distributorService.getPage(pageReqVO);
        List<DistributorDO> list = page.getList();

        // 获取用户
        List<Long> ids = CollectionUtils.convertList(list, DistributorDO::getId);
        List<DistributorUserDO> userList = distributorUserService.getUserList(new DistributorUserExportReqVO().setSuperiorIdP1s(ids));
        Map<Long, List<DistributorUserDO>> map = userList.stream().collect(Collectors.groupingBy(DistributorUserDO::getSuperiorIdP1));

        // 组装用户数量
        list.forEach(distributorDO -> {
            DistributorLevelDO distributorLevelDO = distributorLevelMap.get(distributorDO.getLevelId());
            distributorDO.setLevelName(distributorLevelDO.getName());
            if (CollUtil.isNotEmpty(map)) {
                List<DistributorUserDO> distributorUserDOS = map.get(distributorDO.getId());
                if (CollUtil.isNotEmpty(distributorUserDOS)) {
                    distributorDO.setUserCount(distributorUserDOS.size());
                } else {
                    distributorDO.setUserCount(0);
                }
            }
        });
        return page;
    }

}
